﻿Option Strict On
Option Explicit On
Option Infer On

Imports System
Imports GenDotNet.TemplateSupport
Imports GenDotNet.Task.Common
Imports GenDotNet.ObjectModel

Public Class PropertyInfo
   Inherits MemberInfo

   Private mType As NetTypeInfo
   Private mIsReadOnly As Boolean
   Private mGetMethodDelegate As EmptyDelegate
   Private mSetMethodDelegate As EmptyDelegate
   Private mGetAttributes As AttributeInfoCollection
   Private mSetAttributes As AttributeInfoCollection

   Public Sub New( _
            ByVal name As String, _
            ByVal typeInfo As TypeInfo, _
            ByVal scope As Scope, _
            ByVal modifiers As MemberModifiers, _
            ByVal type As NetTypeInfo, _
            ByVal isReadonly As Boolean, _
            ByVal getMethodDelegate As EmptyDelegate, _
            ByVal setMethodDelegate As EmptyDelegate, _
            ByVal ParamArray parameters() As ParameterInfo)
      MyBase.New(name, typeInfo, scope, modifiers, parameters)
      Me.mType = type
      Me.mIsReadOnly = isReadonly
      Me.mGetMethodDelegate = getMethodDelegate
      Me.mSetMethodDelegate = setMethodDelegate
      Me.mGetAttributes = New AttributeInfoCollection
      Me.mSetAttributes = New AttributeInfoCollection
   End Sub

   Public Sub New( _
             ByVal name As String, _
             ByVal typeInfo As TypeInfo, _
             ByVal scope As Scope, _
             ByVal modifiers As MemberModifiers, _
            ByVal interfaceItem As InterfaceItemInfo, _
             ByVal type As NetTypeInfo, _
             ByVal isReadonly As Boolean, _
             ByVal getMethodDelegate As EmptyDelegate, _
             ByVal setMethodDelegate As EmptyDelegate, _
             ByVal ParamArray parameters() As ParameterInfo)
      MyBase.New(name, typeInfo, scope, modifiers, parameters)
      Me.mType = type
      Me.mIsReadOnly = isReadonly
      Me.mGetMethodDelegate = getMethodDelegate
      Me.mSetMethodDelegate = setMethodDelegate
      Me.mGetAttributes = New AttributeInfoCollection
      Me.mSetAttributes = New AttributeInfoCollection
      Me.InterfaceItems.Add(interfaceItem)
   End Sub

   Public Sub New( _
             ByVal name As String, _
             ByVal typeInfo As TypeInfo, _
             ByVal scope As Scope, _
             ByVal type As NetTypeInfo, _
             ByVal isReadonly As Boolean, _
             ByVal getMethodDelegate As EmptyDelegate, _
             ByVal setMethodDelegate As EmptyDelegate, _
             ByVal ParamArray parameters() As ParameterInfo)
      Me.New(name, typeInfo, scope, Nothing, type, isReadonly, getMethodDelegate, setMethodDelegate, parameters)
   End Sub

   Public Sub New( _
            ByVal name As String, _
            ByVal typeInfo As TypeInfo, _
            ByVal scope As Scope, _
            ByVal type As NetTypeInfo, _
            ByVal getMethodDelegate As EmptyDelegate, _
            ByVal setMethodDelegate As EmptyDelegate, _
            ByVal ParamArray parameters() As ParameterInfo)
      Me.New(name, typeInfo, scope, Nothing, type, False, getMethodDelegate, setMethodDelegate, parameters)
   End Sub

   Public Sub New( _
            ByVal name As String, _
            ByVal typeInfo As TypeInfo, _
            ByVal scope As Scope, _
            ByVal type As NetTypeInfo, _
            ByVal isReadonly As Boolean, _
            ByVal getMethodDelegate As EmptyDelegate, _
            ByVal ParamArray parameters() As ParameterInfo)
      Me.New(name, typeInfo, scope, Nothing, type, isReadonly, getMethodDelegate, Nothing, parameters)
   End Sub

   Public Sub New( _
            ByVal name As String, _
            ByVal typeInfo As TypeInfo, _
            ByVal scope As Scope, _
            ByVal type As NetTypeInfo, _
            ByVal getMethodDelegate As EmptyDelegate, _
            ByVal ParamArray parameters() As ParameterInfo)
      Me.New(name, typeInfo, scope, Nothing, type, False, getMethodDelegate, Nothing, parameters)
   End Sub

   Public Sub New( _
            ByVal name As String, _
            ByVal typeInfo As TypeInfo, _
            ByVal scope As Scope, _
            ByVal type As NetTypeInfo, _
            ByVal ParamArray parameters() As ParameterInfo)
      Me.New(name, typeInfo, scope, Nothing, type, False, Nothing, Nothing, parameters)
   End Sub

   'Public Sub New( _
   '         ByVal name As String, _
   '         ByVal typeInfo As TypeInfo, _
   '         ByVal scope As Scope, _
   '         ByVal modifiers As MemberModifiers, _
   '         ByVal type As StandardNetType, _
   '         ByVal isReadonly As Boolean, _
   '         ByVal getMethodDelegate As EmptyDelegate, _
   '         ByVal setMethodDelegate As EmptyDelegate, _
   '         ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, New NetTypeInfo(type), isReadonly, getMethodDelegate, setMethodDelegate, parameters)
   'End Sub

   'Public Sub New( _
   '          ByVal name As String, _
   '          ByVal typeInfo As TypeInfo, _
   '          ByVal scope As Scope, _
   '          ByVal type As StandardNetType, _
   '          ByVal isReadonly As Boolean, _
   '          ByVal getMethodDelegate As EmptyDelegate, _
   '          ByVal setMethodDelegate As EmptyDelegate, _
   '          ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, type, isReadonly, getMethodDelegate, setMethodDelegate, parameters)
   'End Sub

   'Public Sub New( _
   '         ByVal name As String, _
   '         ByVal typeInfo As TypeInfo, _
   '         ByVal scope As Scope, _
   '         ByVal type As StandardNetType, _
   '         ByVal getMethodDelegate As EmptyDelegate, _
   '         ByVal setMethodDelegate As EmptyDelegate, _
   '         ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, type, False, getMethodDelegate, setMethodDelegate, parameters)
   'End Sub

   'Public Sub New( _
   '         ByVal name As String, _
   '         ByVal typeInfo As TypeInfo, _
   '         ByVal scope As Scope, _
   '         ByVal type As StandardNetType, _
   '         ByVal isReadonly As Boolean, _
   '         ByVal getMethodDelegate As EmptyDelegate, _
   '         ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, type, isReadonly, getMethodDelegate, Nothing, parameters)
   'End Sub

   'Public Sub New( _
   '         ByVal name As String, _
   '         ByVal typeInfo As TypeInfo, _
   '         ByVal scope As Scope, _
   '         ByVal type As StandardNetType, _
   '         ByVal getMethodDelegate As EmptyDelegate, _
   '         ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, type, False, getMethodDelegate, Nothing, parameters)
   'End Sub

   'Public Sub New( _
   '         ByVal name As String, _
   '         ByVal typeInfo As TypeInfo, _
   '         ByVal scope As Scope, _
   '         ByVal type As StandardNetType, _
   '         ByVal ParamArray parameters() As ParameterInfo)
   '   Me.New(name, typeInfo, scope, Nothing, type, False, Nothing, Nothing, parameters)
   'End Sub

   Public ReadOnly Property Type() As NetTypeInfo
      Get
         Return mType
      End Get
   End Property

   Public ReadOnly Property IsReadOnly() As Boolean
      Get
         Return mIsReadOnly
      End Get
   End Property

   Public ReadOnly Property SetMethodDelegate() As EmptyDelegate
      Get
         Return mSetMethodDelegate
      End Get
   End Property

   Public ReadOnly Property GetMethodDelegate() As EmptyDelegate
      Get
         Return mGetMethodDelegate
      End Get
   End Property

   Public ReadOnly Property GetAttributes() As AttributeInfoCollection
      Get
         Return mGetAttributes
      End Get
   End Property

   Public ReadOnly Property SetAttributes() As AttributeInfoCollection
      Get
         Return mSetAttributes
      End Get
   End Property

End Class


Namespace VB
   Public Module PropertyInfoExtensions
      '      <Runtime.CompilerServices.Extension()> _
      '      Public Function Output( _
      '               ByVal info As PropertyInfo, _
      '               ByVal data As Object) _
      '               As String
      '         Dim getMethod = info.GetMethodDelegate
      '         Dim setMethod = info.SetMethodDelegate
      '         If getMethod Is Nothing Then
      '            getMethod = AddressOf DefaultGetMethod
      '         End If
      '         If setMethod Is Nothing Then
      '            setMethod = AddressOf DefaultSetMethod
      '         End If
      '         Return _
      '<code>
      '   <%= info.Attributes.Output %>
      '   <%= info.Scope.Output %>
      '   <%= Spaces(3) %>
      '   <%= If(info.IsReadOnly, "ReadOnly ", String.Empty) %>Property <%= info.Name %>(<%= info.Parameters.Output %>) As <%= info.Type.Output %>
      '   <%= info.GetAttributes.Output %>
      '      Get <%= getMethod.Invoke(New PropertyEventArgs(info, data)) %>
      '      End Get<%= Strings.nws %>
      '   <%= If(Not info.IsReadOnly, _
      '      <code>
      '         <%= info.SetAttributes.Output %>
      '      Set (ByVal value As <%= info.Type.Output %>)<%= setMethod.Invoke(New PropertyEventArgs(info, data)) %>
      '      End Set<%= Strings.nws %>
      '      </code>.Value, String.Empty) %>
      '   End Property <%= Strings.CrLf %><%= Strings.CrLf %>
      '</code>.Value
      '      End Function

      <System.Runtime.CompilerServices.Extension()> _
     Public Function Output( _
                ByVal info As PropertyInfo) _
                As String
         Return Output(info, False)
      End Function

      <System.Runtime.CompilerServices.Extension()> _
     Public Function Output( _
                ByVal info As PropertyInfo, _
                ByVal forceReadOnly As Boolean) _
                As String
         Dim getMethod = info.GetMethodDelegate
         Dim setMethod = info.SetMethodDelegate
         If getMethod Is Nothing Then
            getMethod = Function() DefaultGetMethod(info)
         End If
         If setMethod Is Nothing Then
            setMethod = Function() DefaultSetMethod(info)
         End If
         Dim isReadonly = forceReadOnly Or info.IsReadOnly
         Return _
<code>
   <%= info.Attributes.Output %>
   <%= info.Scope.Output.WithSpace %>
   <%= info.Modifiers.Output.WithSpace %>
   <%= If(isReadonly, "ReadOnly ", String.Empty) %>Property <%= info.Name %>(<%= info.Parameters.Output %>) As <%= info.Type.Output %><%= info.InterfaceItems.OutputDeclaration %><%= Strings.nl %>
   <%= info.GetAttributes.Output %>
      Get 
<%= getMethod.Invoke() %>
      End Get
   <%= If(Not isReadonly, _
      <code>
         <%= info.SetAttributes.Output %>
      Set (ByVal value As <%= info.Type.Output %>)
<%= setMethod.Invoke() %>
      End Set<%= Strings.nws %>
      </code>.Value, String.Empty) %>
   End Property <%= Strings.nl %><%= Strings.nl %>
</code>.Value
      End Function

      Private Function DefaultGetMethod(ByVal info As PropertyInfo) As String
         Return _
<code>
         Return m<%= info.Name %>
</code>.Value
      End Function

      Private Function DefaultSetMethod(ByVal info As PropertyInfo) As String
         ' Assume preceding "m"
         Return _
<code>
         m<%= info.Name %> = Value<%= Strings.nws %>
</code>.Value
      End Function

      <System.Runtime.CompilerServices.Extension()> _
   Public Function OutputStringValue(ByVal prop As IPropertyData) As String
         If prop.NetType = StandardNetType.String Then
            Return _
   <code>
            If Me.<%= prop.Name %> IsNot Nothing Then
               ret += Me.<%= prop.Name %>
            End If
   </code>.Value
         ElseIf prop.NetType = StandardNetType.Guid Then
            Return _
   <code>
            ret += Me.<%= prop.Name %>.ToString()
   </code>.Value
         Else
            Return _
  <code>
            ret += Me.<%= prop.Name %>.ToString(System.Globalization.CultureInfo.CurrentUICulture)
  </code>.Value
         End If
      End Function

   End Module

End Namespace

Namespace CSharp
   Public Module PropertyInfoExtensions
      ' NOTE: Interfaces not yet implemented for C# templates
      <System.Runtime.CompilerServices.Extension()> _
     Public Function Output( _
                ByVal info As PropertyInfo) _
                As String
         Return Output(info, False)
      End Function

      <System.Runtime.CompilerServices.Extension()> _
     Public Function Output( _
                ByVal info As PropertyInfo, _
                ByVal forceReadOnly As Boolean) _
                As String
         Dim getMethod = info.GetMethodDelegate
         Dim setMethod = info.SetMethodDelegate
         If getMethod Is Nothing Then
            getMethod = Function() DefaultGetMethod(info)
         End If
         If setMethod Is Nothing Then
            setMethod = Function() DefaultSetMethod(info)
         End If
         Dim isReadOnly = forceReadOnly Or info.IsReadOnly
         ' NOTE: This does not support parameters on properties
         Return _
<code>
   <%= info.Attributes.Output %>
   <%= info.Scope.Output %>
   <%= Spaces(3) %>
   <%= info.Type.Output.WithSpace %><%= info.Name %>
   {
   <%= info.GetAttributes.Output %>
      get 
      {
      <%= getMethod.Invoke().WithSemiColons %>
      } <%= Strings.nws %>
   <%= If(Not isReadOnly, _
      <code>
         <%= info.SetAttributes.Output %>
      set 
      {
         <%= setMethod.Invoke().WithSemiColons %>
      }<%= Strings.nws %>
      </code>.Value, String.Empty) %>
   } <%= Strings.nl %><%= Strings.nl %>
</code>.Value
      End Function

      Private Function DefaultGetMethod(ByVal info As PropertyInfo) As String
         Return _
<code>
         return m<%= info.Name %>;
</code>.Value
      End Function

      Private Function DefaultSetMethod(ByVal info As PropertyInfo) As String
         ' Assume preceding "m"
         Return _
<code>
         m<%= Info.Name %> = value;<%= Strings.nws %>
</code>.Value
      End Function

      <System.Runtime.CompilerServices.Extension()> _
Public Function OutputStringValue(ByVal prop As IPropertyData) As String
         If prop.NetType = StandardNetType.String Then
            Return _
   <code>
            if (Me.<%= prop.Name %> IsNot Nothing)
            {
               ret += Me.<%= prop.Name %>;
            }
   </code>.Value
         ElseIf prop.NetType = StandardNetType.Guid Then
            Return _
   <code>
            ret += Me.<%= prop.Name %>.ToString();
   </code>.Value
         Else
            Return _
  <code>
            ret += Me.<%= prop.Name %>.ToString(System.Globalization.CultureInfo.CurrentUICulture);
  </code>.Value
         End If
      End Function


   End Module
End Namespace
